﻿

using Newtonsoft.Json;
using StackExchange.Profiling.Internal;
using System.Text.Json;
using WeChatV3Pay.Application.Transactions.Dtos.JsApi;
using WeChatV3Pay.Core;

namespace WeChatV3Pay.Application.Transactions.Services
{
    public class TransactionsService : ITransactionsService, ITransient
    {
        /// <summary>
        /// JSAPI下单
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        /// <remarks>商户系统先调用该接口在微信支付服务后台生成预支付交易单，返回正确的预支付交易会话标识后再按Native、JSAPI、APP等不同场景生成交易串调起支付。</remarks>
        public async Task<JSBridgeRes> JsApiPayAsync([NotNull] JsApiPayReq request)
        {
            request.TryValidate();
            var path = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
            var req = request.Adapt<JsApiPayDto>();

            var jsApiPayRes = await path.SetBody(req)
                .SetJsonSerialization<NewtonsoftJsonSerializerProvider>(new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore
                })
                .SetHeaders(new Dictionary<string, object>
                {
                    {"Accept","*/*" },
                })
                .OnRequesting(async (client, req) =>
                {
                    var body = await req.Content.ReadAsStringAsync();
                    var sign = WeChatStringHelper.Sign(req.Method.ToString(), req.RequestUri.PathAndQuery, body, request.PrivateKey, request.SerialNo, request.MchId);
                    req.Headers.Add("Authorization", sign);
                })
                .OnException((client, res, error) =>
                {

                }).PostAsAsync<JsApiPayRes>();
            if (string.IsNullOrWhiteSpace(jsApiPayRes.PrepayId))
            {
                throw Oops.Bah($"{jsApiPayRes.Code}{jsApiPayRes.Message}");
            }
            else
            {
                var signType = "RSA";
                var jsBridge = new JSBridgeRes()
                {
                    AppId = request.AppId,
                    NonceStr = Guid.NewGuid().ToString().Replace("-", ""),
                    Package = "prepay_id=" + jsApiPayRes.PrepayId,
                    SignType = signType,
                    TimeStamp = WeChatStringHelper.GenerateTimeStamp()
                };

                jsBridge.PaySign = WeChatStringHelper.MakeSign(request.PrivateKey, jsBridge.AppId, jsBridge.TimeStamp, jsBridge.NonceStr, jsBridge.Package);
                return jsBridge;
            }
        }

        /// <summary>
        /// 根据系统生成的订单号查询订单
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<QueryTransactionRes> QueryTransactionsByIdAsync([NotNull] QueryTransactionReq request)
        {
            var path = $"https://api.mch.weixin.qq.com/v3/pay/transactions/id/{request.SearchKey}";
            return await path.SetHeaders(new Dictionary<string, object>
                {
                    {"Accept","*/*" },
                })
                .SetQueries(new Dictionary<string, object>
                {
                    {"mchid",request.MchId }
                })
                .OnRequesting((client, req) =>
                {
                    var sign = WeChatStringHelper.Sign(req.Method.ToString(), req.RequestUri.PathAndQuery, "", request.PrivateKey, request.SerialNo, request.MchId);
                    req.Headers.Add("Authorization", sign);
                })
                .OnException((client, res, error) =>
                {
                }).GetAsAsync<QueryTransactionRes>();
        }

        /// <summary>
        /// 根据商户系统内部订单号查询订单
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<QueryTransactionRes> QueryTransactionsByOutTradeNOAsync([NotNull] QueryTransactionReq request)
        {
            var path = $"https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{request.SearchKey}";
            return await path.SetHeaders(new Dictionary<string, object>
                {
                    {"Accept","*/*" },
                })
                .SetQueries(new Dictionary<string, object>
                {
                    {"mchid",request.MchId }
                }).OnRequesting((client, req) =>
                {
                    var sign = WeChatStringHelper.Sign(req.Method.ToString(), req.RequestUri.PathAndQuery, "", request.PrivateKey, request.SerialNo, request.MchId);
                    req.Headers.Add("Authorization", sign);
                })
                .OnException((client, res, error) =>
                {
                }).GetAsAsync<QueryTransactionRes>();
        }

        /// <summary>
        /// 关闭订单
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task CloseTransactionsAsync([NotNull] CloseTransactionReq request)
        {
            var path = $"https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{request.OutTradeNo}/close";
            await path.SetHeaders(new Dictionary<string, object>
                {
                    {"Accept","*/*" },
                })
                .SetBody(new
                {
                    mchid = request.MchId
                })
                .SetJsonSerialization<NewtonsoftJsonSerializerProvider>(new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore
                }).OnRequesting(async (client, req) =>
               {
                   var body = await req.Content.ReadAsStringAsync();
                   var sign = WeChatStringHelper.Sign(req.Method.ToString(), req.RequestUri.PathAndQuery, body, request.PrivateKey, request.SerialNo, request.MchId);
                   req.Headers.Add("Authorization", sign);
               })
               .OnException((client, res, error) =>
               {
               }).PostAsync();
        }
    }
}
